package ryanbrown.tictactoe.server;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;

import ryanbrown.tictactoe.TicTacToeConstants;

public class HandleASession implements Runnable, TicTacToeConstants {
	private Socket player1, player2;
	private char[][] cell = new char[3][3];
	private boolean continueToPlay = true;

	public HandleASession(Socket player1, Socket player2) {
		this.player1 = player1;
		this.player2 = player2;

		for (int i = 0; i < 3; i++)
			for (int j = 0; j < 3; j++)
				cell[i][j] = ' ';
	}

	public void run() {
		try {
			DataInputStream fromPlayer1 = new DataInputStream(player1.getInputStream());
			DataOutputStream toPlayer1 = new DataOutputStream(player1.getOutputStream());
			DataInputStream fromPlayer2 = new DataInputStream(player2.getInputStream());
			DataOutputStream toPlayer2 = new DataOutputStream(player2.getOutputStream());

			// Write anything to notify player 1 to start
			toPlayer1.writeInt(1);

			// Continuously serve the players and determine and report the game status
			// to the players
			while (true) {
				int row = fromPlayer1.readInt();
				int column = fromPlayer1.readInt();

				cell[row][column] = 'X';

				// Check if Player 1 wins
				if (isWon('X')) {
					toPlayer1.writeInt(PLAYER1_WON);
					toPlayer2.writeInt(PLAYER1_WON);
					sendMove(toPlayer2, row, column);
					break;
				} else if (isFull()) {
					toPlayer1.writeInt(DRAW);
					toPlayer2.writeInt(DRAW);
					sendMove(toPlayer2, row, column);
					break;
				} else {
					toPlayer2.writeInt(CONTINUE);
					sendMove(toPlayer2, row, column);
				}

				row = fromPlayer2.readInt();
				column = fromPlayer2.readInt();
				cell[row][column] = 'O';

				// Check if Player 2 wins
				if (isWon('O')) {
					toPlayer1.writeInt(PLAYER2_WON);
					toPlayer2.writeInt(PLAYER2_WON);
					sendMove(toPlayer1, row, column);
					break;
				} else {
					toPlayer1.writeInt(CONTINUE);
					sendMove(toPlayer1, row, column);
				}
			}
		}
		catch (IOException ex) {
			System.err.println(ex);
		}
	}

	private void sendMove(DataOutputStream out, int row, int column) throws IOException {
		out.writeInt(row);
		out.writeInt(column);
	}

	private boolean isFull() {
		for (int i = 0; i < 3; i++) {
			for (int j = 0; j < 3; j++) {
				if (cell[i][j] == ' ') {
					return false;
				}
			}
		}
		return true;
	}

	private boolean isWon(char token) {
		// Check all rows
		for (int i = 0; i < 3; i++) {
			if ((cell[i][0] == token) && (cell[i][1] == token) && (cell[i][2] == token)) {
				return true;
			}
		}

		// Check all columns
		for (int j = 0; j < 3; j++) {
			if ((cell[0][j] == token) && (cell[1][j] == token) && (cell[2][j] == token)) {
				return true;
			}
		}

		// Check major diagonal
		if ((cell[0][0] == token) && (cell[1][1] == token) && (cell[2][2] == token)) {
			return true;
		}

		// Check subdiagonal
		if ((cell[0][2] == token) && (cell[1][1] == token) && (cell[2][0] == token)) {
			return true;
		}

		return false;
	}
}
